package com.fintech.third.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.net.URL;
import java.nio.charset.Charset;
import java.rmi.RemoteException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Random;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.namespace.QName;
import javax.xml.rpc.ParameterMode;

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fintech.third.constant.DataRow;
import com.marvels.common.utils.MarvelsLogUtil;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.mapper.MapperWrapper;


import net.sf.json.JSONObject;


@Component
public class ThirdSystemUtil {
	private static final String Transformation = "DESede/CBC/PKCS5Padding";
	private static final String Algorithm = "DESede";
	private static final String Iv = "\0\0\0\0\0\0\0\0";

	private static String configPropertiesPath;
	
	public  String getConfigPropertiesPath() {
		return configPropertiesPath;
	}
	
	@Value("${config.properties.path}")
	public  void setConfigPropertiesPath(String configPropertiesPath) {
		ThirdSystemUtil.configPropertiesPath = configPropertiesPath;
	}
	
	public static String fillStringByArgs(String str, String... arr) {
		Matcher m = Pattern.compile("\\{(\\d)\\}").matcher(str);
		while (m.find()) {
			str = str.replace(m.group(), arr[Integer.parseInt(m.group(1))]);
		}
		return str;
	}

	/**
	 * 返回指定长度的随机数
	 * 
	 * @param strLength
	 * @return
	 */
	public static String getRandom(int strLength) {
		Random rm = new Random();
		// 获得随机数
		double pross = (1 + rm.nextDouble()) * Math.pow(10, strLength);
		// 将获得的获得随机数转化为字符串
		String fixLenthString = String.valueOf(pross);
		// 返回固定的长度的随机数
		return fixLenthString.substring(1, strLength + 1);
	}

	/**
	 * 获取length长度的随机数(整数)
	 * 
	 * @param length
	 * @return
	 */
	public static String randomNumber(int length) {
		StringBuilder stringBuilder = new StringBuilder();
		for (int i = 0; i < length; i++) {
			stringBuilder.append((int) (1 + Math.random() * 9));
		}
		return stringBuilder.toString();
	}

	public static String getUUID() {
		UUID uuid = UUID.randomUUID();
		String str = uuid.toString();
		// 去掉"-"符号
		String temp = str.replace("-", "").substring(0, 12);
		return temp;
	}

	public static String createUUID(String sign) {
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddhhmmss");
		String timeStr = simpleDateFormat.format(new Date());
		UUID uuid = UUID.randomUUID();
		String str = uuid.toString();
		// 去掉"-"符号
		String temp = str.replace("-", "").substring(0, 5);
		return timeStr + temp + sign;
	}

	public static String getPath() {
		// file:/D:/JavaWeb/.metadata/.me_tcat/webapps/TestBeanUtils/WEB-INF/classes/
		String path = Thread.currentThread().getContextClassLoader().getResource("").toString();
		path = path.replace('/', '\\'); // 将/换成\
		path = path.replace("file:", ""); // 去掉file:
		// path = path.replace("classes\\", ""); // 去掉class\
		path = path.substring(1); // 去掉第一个\,如 \D:\JavaWeb...
		// System.out.println(path);
		return path;
	}

	/**
	 * 将JSON字符串解析成实体
	 * 
	 * @param jsonStr
	 * @param clazz
	 * @return
	 */
	public static <T> T JsonToEntity(String jsonStr, Class<T> clazz) {

		return JSON.parseObject(jsonStr, clazz);

	}

	/**
	 * 将xml解析到实体
	 * 
	 * @param jsonStr
	 * @param clazz
	 * @return
	 */
	public static <T> T xmlToEntity(String xmlStr, Class<T> cls) {
		// 注意：不是new Xstream(); 否则报错：java.lang.NoClassDefFoundError:
		// org/xmlpull/v1/XmlPullParserFactory
		XStream xstream = new XStream() {
			@Override
			protected MapperWrapper wrapMapper(MapperWrapper next) {
				return new MapperWrapper(next) {
					@Override
					public boolean shouldSerializeMember(Class definedIn, String fieldName) {
						if (definedIn == Object.class) {
							try {
								return this.realClass(fieldName) != null;
							} catch (Exception e) {
								return false;
							}
						} else {
							return super.shouldSerializeMember(definedIn, fieldName);
						}
					}
				};
			}
		};
		// xstream.ignoreUnknownElements();
		xstream.processAnnotations(cls);
		T obj = (T) xstream.fromXML(xmlStr);
		return obj;
	}

	/**
	 * 将json转化为实体POJO
	 * 
	 * @param jsonStr
	 * @param obj
	 * @return
	 */
	public static <T> Object JSONToObj(String jsonStr, Class<T> obj) {
		T t = null;
		try {
			ObjectMapper objectMapper = new ObjectMapper();
			t = objectMapper.readValue(jsonStr, obj);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return t;
	}

	/**
	 * 将实体POJO转化为JSON
	 * 
	 * @param obj
	 * @return
	 * @throws JSONException
	 * @throws IOException
	 */
	public static <T> JSONObject objectToJson(T obj) {
		ObjectMapper mapper = new ObjectMapper();
		// Convert object to JSON string
		String jsonStr = "";
		try {
			jsonStr = mapper.writeValueAsString(obj);
		} catch (JsonProcessingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return JSONObject.fromObject(jsonStr);
	}

	/**
	 * 将实体POJO转化为JSON
	 * 
	 * @param obj
	 * @return
	 * @throws JSONException
	 * @throws IOException
	 */
	public static <T> String objectToJsonStr(T obj) {
		ObjectMapper mapper = new ObjectMapper();
		// Convert object to JSON string
		String jsonStr = "";
		try {
			jsonStr = mapper.writeValueAsString(obj);
		} catch (JsonProcessingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return jsonStr;
	}

	/**
	 * 将json解析成map
	 * 
	 * @param jsonStr
	 * @return
	 */
	public static Map<String, Object> jsonToMap(String jsonStr) {
		Map<String, Object> data = new HashMap<String, Object>();

		JSONObject jsonObject = JSONObject.fromObject(jsonStr);
		Iterator ite = jsonObject.keys();

		while (ite.hasNext()) {
			String key = ite.next().toString();
			String value = jsonObject.get(key).toString();
			data.put(key, value);
		}

		return data;

	}

	/**
	 * 参数拼装
	 * 
	 * @return
	 */
	public static String paramsAssembling(Map<String, Object> map, String urlStr) {
		StringBuffer urlStringBuffer = new StringBuffer();
		if (StringUtils.isNotEmpty(urlStr)) {
			urlStringBuffer.append(urlStr).append("?");
		}
		int i = 1;
		for (String key : map.keySet()) {
			if (i == map.size()) {
				urlStringBuffer.append(key).append("=").append(map.get(key));
			} else {
				urlStringBuffer.append(key).append("=").append(map.get(key)).append("&");
			}
			i++;
		}
		return urlStringBuffer.toString();

	}

	// public static Properties readProperties(String file_name) {
	// String propertiesPath =
	// SystemUtil.class.getResource(file_name).getPath();
	// try {
	// propertiesPath = URLDecoder.decode(propertiesPath, "UTF-8");
	// } catch (Exception e1) {
	// e1.printStackTrace();
	// return null;
	// }
	// try {
	// InputStream in = new BufferedInputStream(new
	// FileInputStream(propertiesPath));
	// // InputStream in = SystemUtil.class.getResourceAsStream(file_name);
	// Properties thirdProperties = new Properties();
	// thirdProperties.load(in);
	// return thirdProperties;
	// } catch (IOException e) {
	// e.printStackTrace();
	// return null;
	// }
	// }

	public static Properties readProperties(String file_name) {
		try {
			String filePath=configPropertiesPath+ File.separator + file_name;
			File loadFile = new File(filePath);
			InputStream in = new FileInputStream(loadFile);
			Properties thirdProperties = new Properties();
			thirdProperties.load(new InputStreamReader(in,"UTF-8"));
			return thirdProperties;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
	}

	public static Date getAddDate(Date date, int count) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.YEAR, +count);// 当年时间加count年
		date = calendar.getTime();
		return date;
	}

	public static Date getAddDay(Date date, int count) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DATE, +count);// 当年时间加count天
		date = calendar.getTime();
		return date;
	}

	/**
	 * 3des加密
	 * 
	 * @param keybyte
	 * @param src
	 * @return
	 */
	public static String encryptMode(byte[] keybyte, byte[] src) {
		try {
			// 根据给定的字节数组和算法构造一个密钥
			SecretKey deskey = new SecretKeySpec(keybyte, Algorithm);
			// 加密
			IvParameterSpec iv = new IvParameterSpec(Iv.getBytes());
			Cipher c1 = Cipher.getInstance(Transformation);
			c1.init(Cipher.ENCRYPT_MODE, deskey, iv);
			return byte2hex(c1.doFinal(src));
		} catch (java.security.NoSuchAlgorithmException e1) {
			e1.printStackTrace();
		} catch (javax.crypto.NoSuchPaddingException e2) {
			e2.printStackTrace();
		} catch (java.lang.Exception e3) {
			e3.printStackTrace();
		}
		return null;
	}

	public static String byte2hex(byte[] b) { // 一个字节的数，
		// 转成16进制字符串
		String hs = "";
		String stmp = "";
		for (int n = 0; n < b.length; n++) {
			// 整数转成十六进制表示
			stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
			if (stmp.length() == 1)
				hs = hs + "0" + stmp;
			else
				hs = hs + stmp;
		}
		return hs; // 转成大写
	}

	public static String accessWebService(String requestXml) {
		// System.setProperty("javax.net.ssl.trustStore",thirdProperties.getDeploy_properties_path()+
		// "cer/penyuan/test.jks");// 设置可信任的密钥仓库

		System.setProperty("javax.net.ssl.trustStore", "/home/fintech/resource/cer/penyuan/test.jks");// 设置可信任的密钥仓库
		System.setProperty("javax.net.ssl.trustStorePassword", "123456"); // 设置可信任的密钥仓库的密码

		Service sv = new Service(); // new 一个服务
		Call call = null;
		try {
			call = (Call) sv.createCall(); // 创建一个call对象
			call.setTargetEndpointAddress(
					new URL("https://test.pycredit.com:9443/services/WebServiceSingleQuery?wsdl"));
		} catch (Exception e1) {
			e1.printStackTrace();
		} // 设置要调用的接口地址以上一篇的为例子
		call.setOperationName(new QName("queryReport")); // 设置要调用的接口方法
		call.addParameter("userID", org.apache.axis.encoding.XMLType.XSD_STRING, ParameterMode.IN);// 设置参数名
		call.addParameter("password", org.apache.axis.encoding.XMLType.XSD_STRING, ParameterMode.IN);// 设置参数名
																										// //
																										// id
		call.addParameter("queryCondition", org.apache.axis.encoding.XMLType.XSD_STRING, ParameterMode.IN);// 设置参数名
		call.addParameter("returnStyle", org.apache.axis.encoding.XMLType.XSD_STRING, ParameterMode.IN);// 设置参数名//
																										// 第二个参数表示String类型,第三个参数表示入参
		call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING);// 返回参数类型
		// 开始调用方法,假设我传入的参数id的内容是1001
		// 调用之后会根据id返回users信息，以xml格式的字符串返回，也可以json格式主要看对方用什么方式返回
		String result = "";
		try {
			result = (String) call.invoke(new Object[] { "fjwsquery", "mUhteUSd7slkSbRTNwyujQ==", requestXml, "xml" });
		} catch (RemoteException e) {
			e.printStackTrace();
		}
		return result;
	}


	/**
	 * 字符串转时间
	 * 
	 * @param intStr
	 * @return
	 */
	public static int stringToInt(String str) {
		if (StringUtils.isEmpty(str)) {
			return 0;
		} else {
			if (StringUtils.isNumeric(str)) {
				return Integer.parseInt(str);
			} else {
				return 0;
			}

		}
	}

	public static String decodeUnicode(final String dataStr) {
		int start = 0;
		int end = 0;
		final StringBuffer buffer = new StringBuffer();
		while (start > -1) {
			end = dataStr.indexOf("\\u", start + 2);
			String charStr = "";
			if (end == -1) {
				charStr = dataStr.substring(start + 2, dataStr.length());
			} else {
				charStr = dataStr.substring(start + 2, end);
			}
			char letter = (char) Integer.parseInt(charStr, 16); // 16进制parse整形字符串。
			buffer.append(new Character(letter).toString());
			start = end;
		}
		return buffer.toString();
	}

	public static Properties getThirdPropertieQuick() {
		return ThirdSystemUtil.readProperties("deploy.properties");
	}
	
	
	
	/**
	 * 实体转map
	 * @param bean
	 * @return
	 */
	public static Map<String, String> beanToMap(Object bean) {
		Map<String, String> retMap = new LinkedHashMap<String, String>();
		try {
			Class clazz = bean.getClass();
			Field[] fields = clazz.getDeclaredFields();
			for (Field f : fields) {
				f.setAccessible(true);
			}
			for (Field f : fields) {

				String key = f.toString().substring(f.toString().lastIndexOf(".") + 1);
				if (!"serialVersionUID".equals(key)) {
					Object value = f.get(bean);
					retMap.put(key, value == null ? "" : value.toString());
				}
			}
		} catch (Exception e) {
			MarvelsLogUtil.getInstance().error(">>>>>>>>>>>bean转map异常", e);
		}
		return retMap;
	}
	
	
	
	
	public static String getEncrypt(String str,String type) {
		 MessageDigest md = null;
         String strDes = null;
         byte[] bt = str.getBytes();
         try {
			md = MessageDigest.getInstance(type);
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
         md.update(bt);
         return MD5Util.bytesToHex(md.digest());
	}
	public static DataRow xmlToDatarow(String xmlStr)throws Exception{
		DataRow data = new DataRow();
		
        Document doc = DocumentHelper.parseText(xmlStr);
        
        Element root = doc.getRootElement();
        List<Element> list = root.elements();
        for (Element e : list) {
        	data.put(e.getName(), e.getText());
        }
        return data;
	}
}
